package com.ht.api.db;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import javax.sql.DataSource;

import lombok.Data;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;

/**
 * 数据库连接的资源对象
 * @author asq
 * @createTime 2024年11月29日 20:17:58
 */
@Data
@Accessors(chain = true)
@Slf4j
public class DbResource {
	private DataSource ds;
	
	// 内部属性，便于关闭资源
	private Connection con;
	private PreparedStatement ps;
	private ResultSet rs;
	private Statement sm;
	private List<PreparedStatement> psList = new ArrayList<>();

	public static DbResource create(DataSource ds) {
		return new DbResource().setDs(ds);
	}
	
	/**
	 * 获取数据库连接
	 * @return
	 * @throws SQLException
	 */
	public Connection getConnection() throws SQLException {
		this.con = ds.getConnection();
		return con;
	}

	/**
	 * 获取Statement对象
	 * @return
	 * @throws SQLException
	 */
	public Statement createStatement() throws SQLException {
		this.sm = con.createStatement();
		return sm;
	}
	
	/**
	 * 获取PreparedStatement对象
	 * @param sql
	 * @param generateAutoKey 是否需要获取自增长主键
	 * @return
	 * @throws SQLException
	 */
	public PreparedStatement prepareStatement(String sql, boolean generateAutoKey) throws SQLException {
		if (generateAutoKey) {
			this.ps = con.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS);
		} else {
			this.ps = con.prepareStatement(sql);
		}
		return ps;
	}

	/**
	 * 获取批量插入时的PreparedStatement对象
	 * @param sql
	 * @return
	 * @throws SQLException
	 */
	public PreparedStatement prepareBatchStatement(String sql) throws SQLException {
		PreparedStatement psBatch = con.prepareStatement(sql);
		this.psList.add(psBatch);
		return psBatch;
	}

	/**
	 * 获取记录集
	 * @return
	 * @throws SQLException
	 */
	public ResultSet executeQuery() throws SQLException {
		this.rs = ps.executeQuery();
		return this.rs;
	}

	/**
	 * 回滚事务
	 */
	public void rollback() {
		try {
			if (con != null) con.rollback();
		} catch (SQLException e) {
			log.error("[db]回滚事务发生异常：" + e.getMessage(), e);
		}
	}

	/**
	 * 关闭资源
	 */
	public void close() {
		try {
			if (rs != null) rs.close();
			if (ps != null) ps.close();
			for (PreparedStatement p : psList) p.close();
			if (sm != null) sm.close();
			if (con != null) con.close();
		} catch (SQLException e) {
			log.error("[db]关闭数据库资源发生异常：" + e.getMessage(), e);
		}
	}
}
